//@author A0106044W
package logic;
 
import storage.Task;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.logging.Level;

/**
 * 
 * 
 * 	       Sothearith Sreang
 *         All of the Logic part is written by me.
 * 
 */

public class DisplayHandler extends OperationHandler{
	
	String query;
	
	
	private final String SUCCESSFUL_SEARCH = "There are currenty %d tasks with %s found in the list";
	private final String NO_RESULT = "\"%1s\" is not found in the task list.";
	
	private enum FILTER_TYPE {ALL, PENDING, COMPLETE, NORMAL_QUERY};
	
	private final String ALL_FILTER = "ALL";
	private final String PENDING_FILTER = "PENDING";
	private final String COMPLETE_FILTER = "COMPLETE";
	
	private final boolean PENDING = false;
	private final boolean COMPLETE = true;
	
	private final int EMPTY_LIST = 0;
	
	public DisplayHandler(String queryString){
		super();
		query = queryString;
	}
	
	public String execute(){
		
		FILTER_TYPE filterType = setUpFilterType();
		
		executeDisplay(filterType);
		
		return setUpFeedback();
	}
	
	public String getQuery() {
		return query;
	}

	// first level abstraction
	
	private FILTER_TYPE setUpFilterType() {
		
		switch(query.toUpperCase()) {
			case ALL_FILTER:
				return FILTER_TYPE.ALL;
			case PENDING_FILTER:
				return FILTER_TYPE.PENDING;
			case COMPLETE_FILTER:
				return FILTER_TYPE.COMPLETE;
			default:
				return FILTER_TYPE.NORMAL_QUERY;
		}
	}
	
	private void executeDisplay(FILTER_TYPE filterType){
		ArrayList<Task> displayList = new ArrayList<Task>();
		
		switch(filterType) {
			case ALL:
				displayList = displayAllTasks();
				break;
			case PENDING:
				displayList = displayPendingTasks();
				break;
			case COMPLETE:
				displayList = displayCompleteTasks();
				break;
			case NORMAL_QUERY:
				displayList = displayQueryTasks();
				break;
			default:
				Logic.logger.log(Level.SEVERE, "Problems with flexi commands. Invalid query is sent.");
		}
		
		updateSearchTasksList(displayList);
	}
	
	private String setUpFeedback() {
		int size = Logic.getSearchTaskSize();
		String feedback = "";
		
		if(size == EMPTY_LIST) {
			feedback = String.format(NO_RESULT, query);
		} else {
			feedback = String.format(SUCCESSFUL_SEARCH, size, query);
		}
		
		return feedback;
	}

	//second level abstraction
	
	private ArrayList<Task> displayQueryTasks() {
		ArrayList<Task> searchListClone =  storage.searchTask(query);
		return getActualTasks(searchListClone);
	}

	private ArrayList<Task> displayCompleteTasks() {
		ArrayList<Task> searchListClone = allStatusTasksList(COMPLETE);
		return getActualTasks(searchListClone);
	}

	private ArrayList<Task> displayPendingTasks() {
		ArrayList<Task> searchListClone =  allStatusTasksList(PENDING);
		return getActualTasks(searchListClone);
	}
	
	private void updateSearchTasksList(ArrayList<Task> displayList) {
		Logic.changeSearchTaskList(displayList);
	}

	private ArrayList<Task> displayAllTasks() {
		ArrayList<Task> searchListClone = allTasksList();
		return getActualTasks(searchListClone);
	}

	// third level abstraction
	private ArrayList<Task> allStatusTasksList(boolean status) {
		ArrayList<Task> allStatusTasksList = new ArrayList<Task> ();
		
		for (Iterator<Task> tasks = storage.iterator(); tasks.hasNext();) {
			Task t = tasks.next();
			if(t.getDoneStatus() == status) {
				allStatusTasksList.add(t);
			}
		}
		
		return allStatusTasksList;
	}
	
	private ArrayList<Task> allTasksList() {
		ArrayList<Task> allTasksList = new ArrayList<Task>();
		
		for (Iterator<Task> tasks = storage.iterator(); tasks.hasNext();) {
			Task t = tasks.next();
			allTasksList.add(t);
		}
		
		return allTasksList;
	}
	
	private ArrayList<Task> getActualTasks(ArrayList<Task> searchListClone) {
		ArrayList<Task> searchList = new ArrayList<Task>();
		for(Task taskClone: searchListClone) {
			Task task = null;
			try {
				task = super.getTask(taskClone);
			} catch (Exception e) {
				
			}	
			searchList.add(task);
		}	
		return searchList;
	}
}
